#include <cassert>

#include "TLSFBlockHeaderHandler.h"



namespace MemMgr
{

void TLSFBlockHeaderHandler::SetSize(Word* ioBlock, const size_t iSize)
{
	assert(0 == iSize % sizeof(Word)); // Size is multiple of sizeof(Word)
	// Since iSize is multiple of sizeof(Word) the first two least significative bit does not hold size data...
	// these bit are reused to store two flags
	*ioBlock &= 0x00000003;
	*ioBlock |= iSize;
}



void TLSFBlockHeaderHandler::SetSizeAndFlags(Word* ioBlock, const size_t iSize, const Word iFlags)
{
	assert(iFlags <= 0x03);
	assert(0 == iSize % sizeof(Word)); // Size is multiple of sizeof(Word)

	*ioBlock = iSize | iFlags;
}



void TLSFBlockHeaderHandler::SetPrevPhysic(Word* ioBlock, Word* const iPrevPhysicBlock)
{
	*(reinterpret_cast<Word**>(ioBlock + 0x01)) = iPrevPhysicBlock;
}



void TLSFBlockHeaderHandler::SetNextFree(Word* ioBlock, Word* const iNextFreeBlock)
{
	*(reinterpret_cast<Word**>(ioBlock + 0x02)) = iNextFreeBlock;
}



void TLSFBlockHeaderHandler::SetPrevFree(Word* ioBlock, Word* const iPrevFreeBlock)
{
	*(reinterpret_cast<Word**>(ioBlock + 0x03)) = iPrevFreeBlock;
}



void TLSFBlockHeaderHandler::SetAsFree(Word* ioBlock)
{
	*ioBlock |= 0x00000001;
}



void TLSFBlockHeaderHandler::SetAsNotFree(Word* ioBlock)
{
	*ioBlock &= 0xfffffffe;
}



void TLSFBlockHeaderHandler::SetAsLastPhysic(Word* ioBlock)
{
	*ioBlock |= 0x00000002;
}



void TLSFBlockHeaderHandler::SetAsNotLastPhysic(Word* ioBlock)
{
	*ioBlock &= 0xfffffffd;
}



size_t TLSFBlockHeaderHandler::GetSize(const Word* iBlock)
{
	return *iBlock & 0xfffffffc;
}



TLSFBlockHeaderHandler::Word* TLSFBlockHeaderHandler::GetNextFree(Word* iBlock)
{
	assert(IsFree(iBlock));
	return *(reinterpret_cast<Word**>(iBlock + 0x02));
}



TLSFBlockHeaderHandler::Word* TLSFBlockHeaderHandler::GetPrevFree(Word* iBlock)
{
	assert(IsFree(iBlock));

	return *(reinterpret_cast<Word**>(iBlock + 0x03));
}



TLSFBlockHeaderHandler::Word* TLSFBlockHeaderHandler::GetPrevPhysic(Word* iBlock)
{
	return *(reinterpret_cast<Word**>(iBlock + 0x01));
}



TLSFBlockHeaderHandler::Word* TLSFBlockHeaderHandler::GetNextPhysic(Word* iBlock)
{
	return iBlock + HEADER_WORDS_OVERHEAD + GetSize(iBlock)/sizeof(Word);
}



bool TLSFBlockHeaderHandler::IsLastPhysic(Word* iBlock)
{
	return (*iBlock & 0x00000002) > 0;
}



bool TLSFBlockHeaderHandler::IsFree(Word* iBlock)
{
	return (*iBlock & 0x00000001) > 0;
}

};